package com.geekhalo.lego.plugin.entity;


import com.geekhalo.lego.plugin.aggregation.ApplicationTemplate;
import com.geekhalo.lego.plugin.aggregation.JpaRepositoryTemplate;
import com.geekhalo.lego.plugin.aggregation.RepositoryTemplate;
import com.geekhalo.lego.plugin.aggregation.ViewTemplate;
import com.geekhalo.lego.plugin.creator.JavaFileCreator;
import com.geekhalo.lego.plugin.support.template.CreateClassContext;
import com.geekhalo.lego.plugin.support.ui.DocumentUpdateListener;
import com.geekhalo.lego.plugin.support.util.Utils;
import com.intellij.ide.util.ClassFilter;
import com.intellij.ide.util.PackageChooserDialog;
import com.intellij.ide.util.TreeClassChooser;
import com.intellij.ide.util.TreeClassChooserFactory;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiPackage;
import com.intellij.psi.search.GlobalSearchScope;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import static com.geekhalo.lego.plugin.support.util.Utils.*;

public class CreateEntityDialog extends DialogWrapper {
    private Project project;
    private Module appModule;
    private Module domainModule;
    private Module infraModule;

    private JPanel contentPane;
    private JTextField entityPackage;
    private JButton selectPkgForEntity;
    private JTextField entityClassName;
    private JTextField entityParentClass;
    private JButton entityParentSelectButton;
    private JTextField queryRepository;
    private JTextField queryApplication;
    private JTextField entityModuleName;
    private JCheckBox createQueryRepository;
    private JCheckBox createQueryApplication;
    private JCheckBox jpaQueryRepositoryEnable;
    private JTextField jpaQueryRepositoryImplClassName;
    private JTextField viewModule;
    private JTextField viewPkg;
    private JButton selectViewPkgBtn;
    private JTextField viewClassName;
    private JTextField queyApplicationModule;
    private JTextField queryApplicationPkg;
    private JButton selectQueryAppPkg;
    private JTextField queryRepositoryModule;
    private JTextField queryRepositoryPkg;
    private JButton selectQueryRepositoryPkgBtn;
    private JTextField jpaQueryRepositoryModule;
    private JTextField jpaQueryRepositoryPkg;
    private JButton selectJpaQueryRepositoryPkgBtn;
    private JTextField viewParentClass;
    private JButton selectViewParentClassBtn;
    private JTextField idType;
    private JButton selectIdTypeBtn;

    private void init(Project project, String pkg){
        this.project = project;
        // 绑定模块信息
        bindModules();
        // 更新 包信息
        updateByPackage(pkg);

        // 聚合根包改变，更新其他包
        this.entityPackage.getDocument()
                .addDocumentListener(new DocumentUpdateListener(this::updateByPackage));

        registerPkgSelect(project);

        this.entityClassName.getDocument()
                .addDocumentListener(new DocumentUpdateListener(this::onEntityNameChanged));
        this.viewClassName.getDocument()
                .addDocumentListener(new DocumentUpdateListener(this::refreshQueryByViewNameChanged));

        this.queryRepository.getDocument()
                .addDocumentListener(new DocumentUpdateListener(
                        r -> this.jpaQueryRepositoryImplClassName.setText(Utils.createJpaQueryRepositoryImplByRepository(r))));

    }

    private void registerPkgSelect(Project project) {
        // 选择 Agg 所在包
        selectPkgForEntity.addActionListener(e -> {
            PackageChooserDialog chooserDialog = new PackageChooserDialog("请选择包", project);
            if(chooserDialog.showAndGet()) {
                PsiPackage selectedPackage = chooserDialog.getSelectedPackage();
                if (selectedPackage != null) {
                    entityPackage.setText(selectedPackage.getQualifiedName());
                }
            }
        });

        // 选择 Infra 所在包
        selectIdTypeBtn.addActionListener(e -> {
            PackageChooserDialog chooserDialog = new PackageChooserDialog("请选择包", project);
            if(chooserDialog.showAndGet()) {
                PsiPackage selectedPackage = chooserDialog.getSelectedPackage();
                if (selectedPackage != null) {
                    idType.setText(selectedPackage.getQualifiedName());
                }
            }
        });

        // 选择 Entity 父类
        this.entityParentSelectButton.addActionListener(e -> {
            TreeClassChooserFactory factory = TreeClassChooserFactory.getInstance(project);
            // 设置过滤条件，只选择 public 类型的类
            ClassFilter classFilter = psiClass -> psiClass.getModifierList().hasExplicitModifier(PsiModifier.PUBLIC);
            // 弹出选择类的窗口
            TreeClassChooser chooser = factory.createWithInnerClassesScopeChooser("选择聚合根父类", GlobalSearchScope.allScope(project), classFilter, null);
            chooser.showDialog();
            // 获取用户选择的类
            PsiClass selectedClass = chooser.getSelected();
            // 如果用户选择了类，则在控制台输出类名
            if (selectedClass != null) {
                entityParentClass.setText(selectedClass.getQualifiedName());
            }
        });


        // 选择 视图包
        this.selectViewPkgBtn.addActionListener(e->{
            PackageChooserDialog chooserDialog = new PackageChooserDialog("请选择包", project);
            if(chooserDialog.showAndGet()) {
                PsiPackage selectedPackage = chooserDialog.getSelectedPackage();
                if (selectedPackage != null) {
                    viewPkg.setText(selectedPackage.getQualifiedName());
                }
            }
        });

        // 选择视图模型 父类
        this.selectViewParentClassBtn.addActionListener(e->{
            PackageChooserDialog chooserDialog = new PackageChooserDialog("请选择包", project);
            if(chooserDialog.showAndGet()) {
                PsiPackage selectedPackage = chooserDialog.getSelectedPackage();
                if (selectedPackage != null) {
                    viewParentClass.setText(selectedPackage.getQualifiedName());
                }
            }
        });

        // 选择 Query Application 包
        this.selectQueryAppPkg.addActionListener(e->{
            PackageChooserDialog chooserDialog = new PackageChooserDialog("请选择包", project);
            if(chooserDialog.showAndGet()) {
                PsiPackage selectedPackage = chooserDialog.getSelectedPackage();
                if (selectedPackage != null) {
                    queryApplicationPkg.setText(selectedPackage.getQualifiedName());
                }
            }
        });

        // 选择 Query Repository 包
        this.selectQueryRepositoryPkgBtn.addActionListener(e->{
            PackageChooserDialog chooserDialog = new PackageChooserDialog("请选择包", project);
            if(chooserDialog.showAndGet()) {
                PsiPackage selectedPackage = chooserDialog.getSelectedPackage();
                if (selectedPackage != null) {
                    queryRepositoryPkg.setText(selectedPackage.getQualifiedName());
                }
            }
        });

        // 选择 Jpa Query 实现 包
        this.selectJpaQueryRepositoryPkgBtn.addActionListener(e->{
            PackageChooserDialog chooserDialog = new PackageChooserDialog("请选择包", project);
            if(chooserDialog.showAndGet()) {
                PsiPackage selectedPackage = chooserDialog.getSelectedPackage();
                if (selectedPackage != null) {
                    jpaQueryRepositoryPkg.setText(selectedPackage.getQualifiedName());
                }
            }
        });
    }

    @Override
    protected void doOKAction() {
        // 在这里添加确认按钮的自定义行为
        super.doOKAction();
        createFiles();
        dispose();
    }

    @Override
    public void doCancelAction() {
        super.doCancelAction();
        dispose();
    }
    /**
     * 绑定 Module <br />
     */
    private void bindModules() {
        this.entityModuleName.setText(this.domainModule.getName());

        this.viewModule.setText(this.domainModule.getName());
        this.queryRepositoryModule.setText(this.domainModule.getName());
        this.queyApplicationModule.setText(this.appModule.getName());
        this.jpaQueryRepositoryModule.setText(this.infraModule.getName());
    }

    /**
     * 更新 pkg
     * @param pkg
     */
    private void updateByPackage(String pkg) {
        if (StringUtils.isNotEmpty(pkg)) {
            entityPackage.setText(pkg);

            this.viewPkg.setText(pkg);
            this.queryRepositoryPkg.setText(pkg);
            this.queryApplicationPkg.setText(Utils.domainPkgToApp(pkg));
            this.jpaQueryRepositoryPkg.setText(Utils.domainPkgToInfra(pkg));
        }

    }

    private void onEntityNameChanged(String agg){
        this.viewClassName.setText(Utils.createViewByAgg(agg));
        this.refreshQueryByViewNameChanged(this.viewClassName.getText());
    }


    private void refreshQueryByViewNameChanged(String viewName) {
        this.queryRepository.setText(createQueryRepositoryByView(viewName));

        this.queryApplication.setText(createQueryApplicationByView(viewName));

        this.jpaQueryRepositoryImplClassName
                .setText(Utils.createJpaQueryRepositoryImplByRepository(this.queryRepository.getText()));
    }


    public CreateEntityDialog(Project project, String pkg, Module appModule, Module domainModule, Module infraModule) {
        super(project);
        this.appModule = appModule;
        this.domainModule = domainModule;
        this.infraModule = infraModule;

        setModal(true);

        // call onCancel() on ESCAPE
        contentPane.registerKeyboardAction(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                doCancelAction();
            }
        }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);

        init(project, pkg);
        init();
    }

    private void createFiles(){
        // 创建 Entity
        {
            EntityTemplate.CreateEntityContext context = new EntityTemplate
                    .CreateEntityContext(this.entityPackage.getText(), this.entityClassName.getText());
            bindCommon(context);
            context.setParentClassFull(entityParentClass.getText());
            context.setTableName(Utils.createTableByEntity(this.entityClassName.getText()));
            String content = EntityTemplate.create(context);
            JavaFileCreator.createJavaFileInPackage(this.project, this.domainModule,
                    this.entityPackage.getText(), this.entityClassName.getText(), content);
        }



        // 创建 View
        {
            ViewTemplate.CreateViewContext context =
                    new ViewTemplate.CreateViewContext(this.viewPkg.getText(), this.viewClassName.getText());
            bindCommon(context);
            context.setParentClassFull(viewParentClass.getText());
            context.setTableName(Utils.createTableByEntity(this.entityClassName.getText()));
            String content = ViewTemplate.create(context);
            JavaFileCreator.createJavaFileInPackage(this.project, this.domainModule,
                    this.viewPkg.getText(), this.viewClassName.getText(), content);
        }



        // 创建 QueryRepository
        if (createQueryRepository.isSelected()){
            RepositoryTemplate.CreateQueryRepositoryContext context = new RepositoryTemplate
                    .CreateQueryRepositoryContext(this.queryRepositoryPkg.getText(), this.queryRepository.getText());
            bindCommon(context);
            context.setViewTypeFull(this.viewPkg.getText() + "." + this.viewClassName.getText());
            context.setViewIdTypeFull(this.idType.getText());
            String queryContent = RepositoryTemplate.createQuery(context);
            JavaFileCreator.createJavaFileInPackage(this.project, this.domainModule,
                    this.queryRepositoryPkg.getText(), this.queryRepository.getText(), queryContent);
        }

        // 创建 QueryApplication
        if (createQueryApplication.isSelected()){
            ApplicationTemplate.CreateQueryApplicationContext context = new ApplicationTemplate
                    .CreateQueryApplicationContext(this.queryApplicationPkg.getText(), this.queryApplication.getText());
            bindCommon(context);
            context.setViewTypeFull(this.viewPkg.getText() + "." + this.viewClassName.getText());
            context.setQueryRepositoryTypeFull(this.queryRepositoryPkg.getText() + "." + this.queryRepository.getText());
            String content = ApplicationTemplate.createQueryApplication(context);
            JavaFileCreator.createJavaFileInPackage(this.project, this.appModule,
                    this.queryApplicationPkg.getText(), this.queryApplication.getText(), content);
        }


        // 创建 JpaBasedQueryRepository
        if (this.jpaQueryRepositoryEnable.isSelected()){
            JpaRepositoryTemplate.CreateJpaQueryRepositoryContext context = new JpaRepositoryTemplate
                    .CreateJpaQueryRepositoryContext(
                            this.jpaQueryRepositoryPkg.getText(),
                            this.jpaQueryRepositoryImplClassName.getText());
            bindCommon(context);

            context.setRepositoryType(this.queryRepositoryPkg.getText(), this.queryRepository.getText());
            context.setViewTypeFull(this.viewPkg.getText() + "." + this.viewClassName.getText());
            context.setViewIdTypeFull(this.idType.getText());
            String content = JpaRepositoryTemplate.createQuery(context);

            JavaFileCreator.createJavaFileInPackage(this.project, this.infraModule,
                    this.jpaQueryRepositoryPkg.getText(),
                    this.jpaQueryRepositoryImplClassName.getText(),
                    content);
        }

    }

    private void bindCommon(CreateClassContext context){
    }

    @Override
    protected @Nullable JComponent createCenterPanel() {
        return contentPane;
    }
}
